/*
 * Tf: a unit test framework for C
 * Copyright (C) 2012 zrezek at gmail.com
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 3.0 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */
#include "tf.h"
#include <stdio.h>
#include <stdlib.h>

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
TF_BEGIN_TEST(test_require)
{
    TF_REQUIRE(1); // pass
}
TF_END_TEST

TF_BEGIN_TEST(test_require_eq)
{
    TF_REQUIRE_EQ(1 + 1, 2); // pass
}
TF_END_TEST

TF_BEGIN_TEST(test_require_neq)
{
    TF_REQUIRE_NEQ(1 + 1, 0); // pass
}
TF_END_TEST

TF_BEGIN_TEST(test_require_close)
{
    TF_REQUIRE_CLOSE(1.0, 1.01, 0.1); // pass
}
TF_END_TEST

TF_BEGIN_FIXTURE(/tf/, macros)
{
    TF_TEST(test_require);
    TF_TEST(test_require_eq);
    TF_TEST(test_require_neq);
    TF_TEST(test_require_close);
}
TF_END_FIXTURE

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
TF_BEGIN_TEST(infinite_loop_test)
{
    for (;;)
        ;
}
TF_END_TEST

TF_BEGIN_TEST(access_violation_test)
{
    unsigned char* invalid_ptr = (unsigned char*) 0;
    
    *invalid_ptr= 0;
}
TF_END_TEST

TF_BEGIN_TEST(division_by_zero)
{
    // call abs to prevent compiler
    // from optimizing expression
    abs(abs(10) / abs(0));
}
TF_END_TEST

TF_BEGIN_FIXTURE(/tf/, crashes)
{
    TF_TEST(infinite_loop_test);
    TF_TEST(access_violation_test);
    TF_TEST(division_by_zero);

    TF_TIMEOUT(10);
}
TF_END_FIXTURE

///////////////////////////////////////////////////////////////
// ensure that call sequence -> setup() test() teardown()
// is called in the right order. as a rule of the thumb it's
// not a good idea to use REQUIRE_xx macros inside setup or
// teardown but in this case there's no other way.
static int x = 0;

TF_BEGIN_TEST(flow_test)
{
    TF_REQUIRE(x++ == 1);
}
TF_END_TEST

void setup_flow()
{
    TF_REQUIRE(x++ == 0);
}

void teardown_flow()
{
    TF_REQUIRE(x++ == 2);
}

TF_BEGIN_FIXTURE(/tf/, flow)
{
    TF_SETUP(setup_flow);
    TF_TEARDOWN(teardown_flow);

    TF_TEST(flow_test);
}
TF_END_FIXTURE

